package com.wmh.baseservice.common.utils.page.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wmh.baseservice.common.mybatisplus.enums.SortMode;
import com.wmh.baseservice.common.mybatisplus.query.FilterReqItem;
import com.wmh.baseservice.common.mybatisplus.structure.CustomQueryWrapper;
import com.wmh.baseservice.common.utils.CommUtil;
import com.wmh.baseservice.common.utils.page.ex.PageException;
import com.wmh.baseservice.common.utils.page.function.PageListOperation;
import com.wmh.baseservice.common.utils.page.pojo.PageInfo;
import com.wmh.baseservice.common.utils.page.pojo.PageResult;
import lombok.Data;
import lombok.experimental.Accessors;

/**
 * 分页工具
 *
 * @author 审心
 */
@Data
@Accessors(chain = true)
public class PageUtil<T> {

    private PageResult<T> pageResult;

    private PageInfo pageInfo;

    private Class<T> entityClass;


    public PageUtil() {
    }

    public PageUtil(PageInfo pageInfo) {
        this.pageInfo = pageInfo;
    }

    public PageUtil(PageInfo pageInfo, Class<T> entityClass){
        this.pageInfo = pageInfo;
        this.entityClass = entityClass;
    }


    /**
     * 开始分页
     *
     * @param pageListOperation 获取数据列表行为函数
     * @return 分页结果
     * @throws PageException 分页异常
     */
    public PageResult<T> startPage(PageListOperation<T> pageListOperation) {
        // 参数校验
        verifyParam(this.pageInfo);

        // 创建条件构造器
        CustomQueryWrapper<T> queryWrapper = new CustomQueryWrapper<>();

        // 分页对象
        Page<T> page = new Page<>(this.pageInfo.getPageNo(), this.pageInfo.getPageSize());

        if (CommUtil.checkNull(this.pageInfo.getIsCount())) {
            page.setSearchCount(this.pageInfo.getIsCount());
        }
        // 追加过滤条件
        if (CollUtil.isNotEmpty(pageInfo.getFilterParams())) {
            FilterReqItem.chainListWrapper(pageInfo.getFilterParams(), queryWrapper, entityClass);
        }
        // 追加排序
        this.chainSortWrapper(queryWrapper);

        // 执行分页列表操作
        pageListOperation.run(page, queryWrapper);

        // 封装返回结果
        PageResult<T> pageResult = new PageResult<T>()
                .setPageNo(page.getCurrent())
                .setPageSize(page.getSize())
                .setList(page.getRecords())
                .setPages(page.getPages())
                .setTotal(page.getTotal());
        setPageResult(pageResult);
        return pageResult;
    }

    /**
     * 校验参数
     *
     * @param page 分页对象
     * @throws PageException 分页异常
     */
    private void verifyParam(PageInfo page) {
        if (null == page) {
            throw new RuntimeException("class 'Paging' is null");
        }
        if (null == page.getPageNo()) {
            throw new RuntimeException("parameter 'pageNo' is null");
        }
        if (null == page.getPageSize()) {
            throw new RuntimeException("parameter 'pageSize' is null");
        }
    }


    private <T> void chainSortWrapper(QueryWrapper<T> wrapper) {
        if (StrUtil.isNotBlank(pageInfo.getSortField())) {
            if (SortMode.DESC.equals(pageInfo.getSortMode())) {
                wrapper.orderByDesc(StrUtil.toUnderlineCase(pageInfo.getSortField()));
            } else {
                wrapper.orderByAsc(StrUtil.toUnderlineCase(pageInfo.getSortField()));
            }
        } else {
            wrapper.orderByDesc("create_time");
        }
    }
}
